import logging
import time
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.schedulers.blocking import BlockingScheduler
import threading
import multiprocessing

from libs.task.cron import get_cron
from typing import Literal

# 配置日志
logger = logging.getLogger(__name__)


class Task:
    """
    任务类，用于封装任务函数及其状态
    """

    def __init__(self, func, cron: str, **kwargs):
        """
        预备任务参数
        :param func: 任务函数
        :param trigger: 触发器类型（例如 'interval', 'cron' 等）
        :param kwargs: 其他传递给任务函数的参数
        """
        self.func = func
        self.trigger = get_cron(cron, True)
        self.kwargs = kwargs
        self.status = 'PENDING'  # 任务状态：PENDING, RUNNING, SUCCESS, FAILED
        self.logger = logger
        self.scheduler = None

    def run(self):
        """
        运行任务
        """
        try:
            self.status = 'RUNNING'
            self.func(**self.kwargs)
            self.status = 'SUCCESS'
        except Exception as e:
            self.status = 'FAILED'
            self.logger.error("任务函数启动失败: %s", str(e))


class APSchedulerBase(object):
    """
    避免程序雪崩， 所有调度任务都放到新线程或进程中执行
    """

    def __init__(self, func, cron, executor_type='thread', mode='background', **kwargs):
        """
        初始化定时任务调度器

        :param func: 任务函数
        :param cron: 触发器类型（例如 'interval', 'cron' 等）
        :param executor_type: 执行器类型（'thread' 或 'process'）
        :param mode: 调度模式（'blocking' 或 'background'）
        :param kwargs: 其他传递给任务函数的参数
        """
        self.task = Task(func, cron, **kwargs)
        self.executor_type = executor_type
        self.mode = mode
        self.scheduler = None
        self.logger = logger
        self.tasks = []
        self.task_count = 0

    @classmethod
    def create_and_start(cls, func, cron, executor_type: Literal['thread', 'process'] = 'thread',
                         mode: Literal['background', 'blocking'] = 'blocking',
                         **kwargs):
        """
        创建并启动定时任务调度器
        :param cron:
        :param func: 任务函数
        :param cron: 触发器类型（例如 'interval', 'cron' 等）
        :param executor_type: 执行器类型（'thread' 或 'process'）
        :param mode: 调度模式（'blocking' 或 'background'）
        :param kwargs: 其他传递给任务函数的参数
        :return: 已经启动的调度器实例
        """

        instance = cls(func, cron, executor_type, mode, **kwargs)
        instance.start_scheduler()
        return instance

    def _add_task(self, job):
        """
        添加任务到任务列表并更新任务计数器
        """
        self.tasks.append(job)
        self.task_count += 1
        self.logger.info(f"任务已添加，当前任务总数: {self.task_count}")

    def start_scheduler(self):
        """
        启动调度器
        """
        try:
            if self.executor_type == 'thread':
                if self.mode == 'blocking':
                    thread = threading.Thread(target=self._blocking_scheduler)
                    thread.start()
                elif self.mode == 'background':
                    thread = threading.Thread(target=self._background_scheduler)
                    thread.start()
                else:
                    raise ValueError("无效的模式。请使用 'blocking' 或 'background'。")
            elif self.executor_type == 'process':
                if self.mode == 'blocking':
                    process = multiprocessing.Process(target=self._blocking_scheduler)
                    process.start()
                elif self.mode == 'background':
                    process = multiprocessing.Process(target=self._background_scheduler)
                    process.start()
                else:
                    raise ValueError("无效的模式。请使用 'blocking' 或 'background'。")
            else:
                raise ValueError("无效的执行器类型。请使用 'thread' 或 'process'。")
        except Exception as e:
            self.logger.error("调度器启动失败: %s", str(e))

    def _blocking_scheduler(self):
        """
        阻塞模式启动调度器
        """
        scheduler = self.get_scheduler()
        self.task.scheduler = scheduler
        scheduler.add_job(func=self.task.run, trigger=self.task.trigger, id=self.task.func.__name__,
                          **self.task.kwargs)
        try:
            scheduler.start()
        except (KeyboardInterrupt, SystemExit):
            scheduler.shutdown()
        except Exception as e:
            self.logger.error("阻塞调度器启动失败: %s", str(e))

    def _background_scheduler(self):
        """
        后台模式启动调度器, 主进程需要一直存活
        """
        scheduler = self.get_scheduler()
        self.task.scheduler = scheduler
        scheduler.add_job(func=self.task.run, trigger=self.task.trigger, id=self.task.func.__name__,
                          **self.task.kwargs)
        try:
            scheduler.start()
        except Exception as e:
            self.logger.error("后台调度器启动失败: %s", str(e))

    def get_scheduler(self):
        """
        获取调度器实例

        :return: 调度器实例
        """
        if self.mode == 'blocking':
            return BlockingScheduler()
        elif self.mode == 'background':
            return BackgroundScheduler()
        else:
            raise ValueError("无效的模式。请使用 'blocking' 或 'background'。")
